﻿using S7.Net;
using System;
using System.Collections.Generic;
using System.Configuration;

namespace SIEMENS
{
    public class PlcCommunicator
    {
        private Plc _plc;
        private readonly static string _ipAddress;
        private readonly static short _rack;
        private readonly static short _slot;
        private readonly static int _port;

        static PlcCommunicator()
        {
            // 读取App.config中的配置，设置默认值防止配置缺失
            _ipAddress = ConfigurationManager.AppSettings["PlcIpAddress"] ?? "192.168.0.1";

            // 转换为short类型（配置文件中是字符串，需显式转换）
            if (!short.TryParse(ConfigurationManager.AppSettings["PlcRack"], out _rack))
            {
                _rack = 0; // 默认值
            }

            if (!short.TryParse(ConfigurationManager.AppSettings["PlcSlot"], out _slot))
            {
                _slot = 1; // 默认值
            }

            if (!int.TryParse(ConfigurationManager.AppSettings["Port"], out _port))
            {
                _port = 2000;
            }
            Instance = new PlcCommunicator(_ipAddress, _port, _rack, _slot); // 初始化单例
        }

        /// <summary>
        /// 单例
        /// </summary>
        public readonly static PlcCommunicator Instance = null;

        public PlcCommunicator()
        {
            // 初始化PLC连接
            _plc = new Plc(CpuType.S71200, _ipAddress, _port, _rack, _slot);
        }

        // 构造函数：初始化PLC参数
        public PlcCommunicator(string ipAddress, int port = 2000, short rack = 0, short slot = 1)
        {
            _plc = new Plc(CpuType.S71200, ipAddress, port, rack, slot); // 默认为S7-1200，可根据型号修改
        }

        // 连接PLC
        public bool Connect()
        {
            try
            {
                if (!_plc.IsConnected)
                {
                    _plc.Open();
                }
                return _plc.IsConnected;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"连接失败：{ex.Message}");
                return false;
            }
        }

        // 断开连接
        public void Disconnect()
        {
            try
            {
                if (_plc.IsConnected)
                {
                    _plc.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"断开连接失败：{ex.Message}");
            }
        }

        // 读取单个地址数据
        public object ReadData(string address)
        {
            if (!this.Connect())
            {
                return null;
            }

            try
            {
                return _plc.Read(address);
            }
            catch (Exception ex)
            {
                Console.WriteLine($"读取地址{address}失败：{ex.Message}");
                return null;
            }
        }

        // 写入单个地址数据
        public bool WriteData(string address, object value)
        {
            if (!this.Connect())
            {
                return false;
            }

            try
            {
                _plc.Write(address, value);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入地址{address}失败：{ex.Message}");
                return false;
            }
        }

        // 批量读取数据
        public Dictionary<string, object> BatchRead(List<string> addresses)
        {
            if (!_plc.IsConnected)
            {
                Console.WriteLine("PLC未连接，无法批量读取");
                return null;
            }

            if (addresses == null || addresses.Count == 0)
            {
                Console.WriteLine("地址列表为空，无需读取");
                return new Dictionary<string, object>();
            }

            var results = new Dictionary<string, object>();

            foreach (var address in addresses)
            {
                try
                {
                    // 循环调用单个读取方法
                    var value = _plc.Read(address);
                    results[address] = value;
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"读取地址{address}失败：{ex.Message}");
                    results[address] = null; // 标记为null表示读取失败
                }
            }

            return results;
        }
    }
}
